﻿using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Taxonomy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Xml.Linq;

namespace SillyFactsWeb
{
    public class Facts
    {
        internal static List<string> GetSillyFacts(Uri hostUrl, string hostAccessToken)
        {
            // Collect facts
            List<string> facts = new List<string>();
            facts.AddRange(GetSearchFacts(hostUrl, hostAccessToken));
            facts.AddRange(GetTaxonomyFacts(hostUrl, hostAccessToken));

            return facts;
        }


        private static IEnumerable<string> GetSearchFacts(Uri hostUrl, string accessToken)
        {
            List<string> facts = new List<string>();
            facts.Add(ExecuteSearchQuery(hostUrl, accessToken, "*"));
            facts.Add(ExecuteSearchQuery(hostUrl, accessToken, "bram"));

            return facts;
        }

        private static string ExecuteSearchQuery(Uri hostUrl, string accessToken, string queryText)
        {
            // REST/OData URL section
            string oDataUrl = string.Format("{0}/_api/search/query?querytext='{1}'", hostUrl, queryText);

            // HTTP Request and Response construction section
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(oDataUrl);
            request.Method = "GET";
            request.Accept = "application/atom+xml";
            request.ContentType = "application/atom+xml;type=entry";
            request.Headers.Add("Authorization", "Bearer " + accessToken);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            // Response markup parsing section
            XDocument oDataXML = XDocument.Load(response.GetResponseStream(), LoadOptions.None);
            XNamespace atom = "http://www.w3.org/2005/Atom";
            XNamespace d = "http://schemas.microsoft.com/ado/2007/08/dataservices";
            XNamespace m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";

            List<XElement> entries = oDataXML.Descendants(d + "query").ToList();

            var entryFieldValues = from entry in entries
                                   select new
                                   {
                                       QueryText = queryText,
                                       ResultCount = entry.Element(d + "PrimaryQueryResult").Element(d + "RelevantResults").Element(d + "TotalRows").Value,
                                       ElapsedTime = entry.Element(d + "ElapsedTime").Value
                                   };

            string fact = string.Format("Searching for <b>{1}</b> returns {0} search results in {2} milliseconds",
                    entryFieldValues.First().ResultCount,
                    entryFieldValues.First().QueryText,
                    entryFieldValues.First().ElapsedTime);

            return fact;
        }

        private static IEnumerable<string> GetTaxonomyFacts(Uri hostUrl, string accessToken)
        {
            List<string> facts = new List<string>();

            using (ClientContext context = TokenHelper.GetClientContextWithAccessToken(hostUrl.OriginalString, accessToken))
            {
                TaxonomySession taxonomySession = TaxonomySession.GetTaxonomySession(context);
                context.Load(taxonomySession, ts => ts.TermStores);
                context.ExecuteQuery();

                TermStore termStore = taxonomySession.TermStores[0];
                context.Load(termStore, ts => ts.Name, ts => ts.WorkingLanguage);

                facts.Add(GetTermSetFact(context, termStore, "Afdeling"));
                facts.Add(GetTermSetFact(context, termStore, "Locatie"));
            }

            return facts;
        }

        private static string GetTermSetFact(ClientContext context, TermStore termStore, string termSetName)
        {
            TermSetCollection termSets = termStore.GetTermSetsByName(termSetName, termStore.WorkingLanguage);
            context.Load(termSets);
            context.ExecuteQuery();

            TermSet departments = termSets[0];
            context.Load(departments.Terms);
            context.ExecuteQuery();

            return string.Format("The term set <b>{0}</b> contains {1} terms.", departments.Name, departments.Terms.Count);
        }


        internal static void AddSillyFacts(List<string> facts, Uri appWebUrl, string appWebAccessToken)
        {
            using (ClientContext context = TokenHelper.GetClientContextWithAccessToken(appWebUrl.ToString(), appWebAccessToken))
            {
                List factsList = context.Web.Lists.GetByTitle("Facts");
                ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();

                foreach (string fact in facts)
                {
                    ListItem factItem = factsList.AddItem(itemCreateInfo);
                    factItem["Title"] = fact;
                    factItem["_Category"] = "Environment";
                    factItem.Update();
                }

                context.ExecuteQuery();
            }
        }
    }
}